package com.system.www.utils;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

/**
 * @author 后台赖骏
 * @version 1.0
 */
public class JdbcUtils {
    //1.使用properties将连接获取

    /**
     *
     */
    public static Connection getConnection() throws IOException, SQLException {
        Properties properties = new Properties();
        properties.load(new FileInputStream("TakeOutSystem/src/com/system/www/config/mysql.properties"));
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String url = properties.getProperty("url");
        return DriverManager.getConnection(url, user, password);
    }

    public static int insert(Object obj) {
        try {
            Connection connection = JdbcUtils.getConnection();
            StringBuilder sb = new StringBuilder();
            sb.append("insert into ");
            Class<?> clz =  obj.getClass();
            String simpleName = clz.getSimpleName();
            sb.append(simpleName).append("(");
            Field[] fields = clz.getDeclaredFields();
            for (Field field : fields) {
                String fieldName = field.getName();
                sb.append(fieldName).append(",");
            }
            sb.deleteCharAt(sb.length() - 1);
            sb.append(") value(null");
            sb.append(",?".repeat(Math.max(0, fields.length - 1)));
            sb.append(");");
            String sql = sb.toString();
            PreparedStatement ps = connection.prepareStatement(sql);
            for (int i = 1; i < fields.length; i++) {
                String fieldName = fields[i].getName();
                String name = "get" + fieldName.toUpperCase().charAt(0)
                        + fieldName.substring(1);
                System.out.println(name);
                Method getObj = clz.getMethod(name);
                Object value = getObj.invoke(obj);
                System.out.println(value);
                ps.setObject(i, value);
            }


            return ps.executeUpdate();
        } catch (SQLException | IOException | InvocationTargetException | NoSuchMethodException | IllegalAccessException  e) {
            e.printStackTrace();
        }

        return 0;
    }

    public static<T> int delete(Class<T> clz, int id) {
        PreparedStatement ps;
        try {
            Connection connection = JdbcUtils.getConnection();
            StringBuilder sb = new StringBuilder();
            sb.append("delete from ");
            String simpleName = clz.getSimpleName();
            sb.append(simpleName);
            sb.append(" where id = ?");
            String sql = sb.toString();
            System.out.println(sql);
            ps = connection.prepareStatement(sql);
            ps.setObject(1, id);
            return ps.executeUpdate();
        } catch (SQLException | IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static int update(Object obj) {
        Connection connection = null;
        StringBuilder sb = new StringBuilder();
        Class<?> clz = obj.getClass();
        sb.append("update ");
        sb.append(obj.getClass().getSimpleName());
        sb.append(" set ");
        Field[] fields = clz.getDeclaredFields();
        for (int i = 1; i < fields.length; i++) {
            sb.append(fields[i].getName()).append(" = ?,");
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append(" where id = ?");
        System.out.println(sb);
        Method method ;
        try {
            connection = JdbcUtils.getConnection();
            PreparedStatement ps = connection.prepareStatement(sb.toString());
            for (int i = 0; i < fields.length; i++) {
                String fieldName = fields[i].getName();
                String methodName = "get" + fieldName.toUpperCase().charAt(0)
                        + fieldName.substring(1);
                System.out.println(methodName);
                method = clz.getMethod(methodName);
                Object value = method.invoke(obj);
                System.out.println(value);
                if (i == 0){
                    ps.setObject(fields.length, value);
                }
                else {
                    ps.setObject(i, value);
                }
            }
            return ps.executeUpdate();
        } catch (NoSuchMethodException | SecurityException | IllegalArgumentException
                | IllegalAccessException | InvocationTargetException | SQLException | IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    public static Object selectSingle(Object obj,String checkField,Object factor) {
        Connection connection = null;
        PreparedStatement ps ;
        ResultSet rs;
        StringBuilder sb = new StringBuilder();
        Class<?> clz =  obj.getClass();
        sb.append("select * from ")
                .append(obj.getClass().getSimpleName()).append(" where ")
                .append(checkField).append(" = ?");
        try {
            connection = JdbcUtils.getConnection();
            ps = connection.prepareStatement(sb.toString());
            ps.setObject(1, factor);
            rs = ps.executeQuery();
            Method[] methods = clz.getMethods();
            if (rs.next()) {
                for (Method method : methods) {
                    if (method.getName().contains("set")){
                        Object value = rs.getObject(method.getName().substring(3));
                        method.invoke(obj, value);
                    }
                }
            }
        } catch (SQLException | IllegalArgumentException | IOException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            try {
                if (connection !=null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return obj;
    }
    public static<T> List<T> selectMore(Class<T> clz) {
        Vector<T> list =null;
        Connection connection = null;
        String sql = "select * from " +
                clz.getSimpleName();
        try {
            connection = JdbcUtils.getConnection();
            PreparedStatement ps= connection.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
            Method[] methods = clz.getMethods();
            list = new Vector<>();
            while(rs.next()){
                T instance = clz.getDeclaredConstructor().newInstance();
                list.add(instance);
                for (Method method: methods) {
                    if (method.getName().contains("set")){

                        Object value = rs.getObject(method.getName().substring(3));
                        method.invoke(instance,value);
                    }
                }
            }

        } catch (IOException | SQLException
                | InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
            e.printStackTrace();
        } finally {
            if (connection != null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return list;
    }
    public static<T> List<T> selectMore(Class<T> clz,String checkField,Object factor) {
        Vector<T> list =null;
        Connection connection = null;
        String sql = "select * from " +
                clz.getSimpleName() + " where " + checkField + "= ?";
        try {
            connection = JdbcUtils.getConnection();
            PreparedStatement ps= connection.prepareStatement(sql);
            ps.setObject(1,factor);
            ResultSet rs = ps.executeQuery();
            Method[] methods = clz.getMethods();
            list = new Vector<>();
            while(rs.next()){
                T instance = clz.getConstructor().newInstance();
                list.add(instance);
                for (Method method: methods) {
                    if (method.getName().contains("set")){

                        Object value = rs.getObject(method.getName().substring(3));
                        method.invoke(instance,value);
                    }
                }
            }

        } catch (IOException | SQLException | InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
            e.printStackTrace();
        } finally {
            if (connection != null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return list;
    }
}
